#include <sstream>
#include <set>
#include "vl_array_prop.h"
#include "vl_node_prop.h"

using namespace VL;


/**
 * @Author: CimZzz
 * @Date: 2022-06-21 14:38:14
 * 
 * 构造方法
 */
ArrayProp::ArrayProp(): VLProp(VLProp::Array) {

}

/**
 * @Author: CimZzz
 * @Date: 2022-06-21 14:38:14
 * 
 * 构造方法
 * @param name 指定数组名
 */
ArrayProp::ArrayProp(std::string name) : VLProp(VLProp::Array) {
	this->setName(name);
}

/**
 * @Author: CimZzz
 * @Date: 2022-06-21 14:39:48
 * 
 * 方法重载, 根据标从数组中获取属性
 * @param index 数组下标
 * @return 属性指针
 */
std::shared_ptr<VLProp> ArrayProp::operator [](unsigned int index) {
	if(index >= this->array.size()) {
		return std::shared_ptr<VLProp>(new VLProp(VLProp::PropType::Empty));
	}

	return this->array[index];
}

/**
 * @Author: CimZzz
 * @Date: 2022-06-21 14:45:06
 * 
 * 数组中添加属性
 * @param prop 属性指针
 */
void ArrayProp::operator ()(VLProp* prop) {
	if(prop == nullptr) {
		return;
	}
	if(this->conflictSet.find(prop->getValue()) == this->conflictSet.end()) {
		conflictSet.emplace(prop->getValue());
		this->array.push_back(std::shared_ptr<VLProp>(prop));
	}
}

/**
 * @Author: CimZzz
 * @Date: 2022-06-21 14:45:06
 * 
 * 数组中添加属性
 * @param prop 属性指针
 */
void ArrayProp::operator ()(std::shared_ptr<VLProp> prop) {
	if(prop.get() == nullptr) {
		return;
	}
	if(this->conflictSet.find(prop->getValue()) == this->conflictSet.end()) {
		conflictSet.emplace(prop->getValue());
		this->array.push_back(prop);
	}
}

/**
 * @Author: CimZzz
 * @Date: 2022-06-21 14:46:35
 * 
 * 数组中直接添加属性值
 * @param prop 属性指针
 */
void ArrayProp::operator ()(std::string propValue) {
	if(this->conflictSet.find(propValue) == this->conflictSet.end()) {
		conflictSet.emplace(propValue);
		this->array.push_back(std::shared_ptr<VLProp>(new NodeProp(propValue)));
	}
}

/**
 * @Author: CimZzz
 * @Date: 2022-06-21 15:25:58
 * 
 * 删除指定下标元素
 * @param index 下标
 */
ArrayProp& ArrayProp::operator -(unsigned int index) {
	auto propValue = this->array.at(index)->getValue();
	this->conflictSet.erase(propValue);
	this->remove(index);
	return *this;
}

/**
 * @Author: CimZzz
 * @Date: 2022-06-21 15:27:00
 * 
 * 数组中添加属性
 * @param prop 属性指针
 */
ArrayProp& ArrayProp::operator +(VLProp* prop) {
	if(prop == nullptr) {
		return *this;
	}
	if(this->conflictSet.find(prop->getValue()) == this->conflictSet.end()) {
		conflictSet.emplace(prop->getValue());
		this->array.push_back(std::shared_ptr<VLProp>(prop));
	}
	return *this;
}

/**
 * @Author: CimZzz
 * @Date: 2022-06-21 15:27:00
 * 
 * 数组中添加属性
 * @param prop 属性指针
 */
ArrayProp& ArrayProp::operator +(std::shared_ptr<VLProp> prop) {
	if(prop.get() == nullptr) {
		return *this;
	}
	if(this->conflictSet.find(prop->getValue()) == this->conflictSet.end()) {
		conflictSet.emplace(prop->getValue());
		this->array.push_back(prop);
	}
	return *this;
}

/**
 * @Author: CimZzz
 * @Date: 2022-06-21 15:27:00
 * 
 * 数组中直接添加属性值
 * @param propValue 属性值
 */
ArrayProp& ArrayProp::operator +(const std::string& propValue) {
	if(this->conflictSet.find(propValue) == this->conflictSet.end()) {
		conflictSet.emplace(propValue);
		this->array.push_back(std::shared_ptr<VLProp>(new NodeProp(propValue)));
	}
	return *this;
}

/**
 * @Author: CimZzz
 * @Date: 2022-06-21 15:27:00
 * 
 * 数组中直接添加属性值
 * 
 * @param propValue 属性值
 */
void ArrayProp::add(const std::string& propValue) {
	if(this->conflictSet.find(propValue) == this->conflictSet.end()) {
		conflictSet.emplace(propValue);
		this->array.push_back(std::shared_ptr<VLProp>(new NodeProp(propValue)));
	}
}

/**
 * @Author: CimZzz
 * @Date: 2022-07-04 18:13:42
 * 
 * 遍历数组属性
 * @param forEachFunc 属性函数
 */
void ArrayProp::foreach(ForEach forEachFunc) {
	for(auto iter = this->array.begin() ; iter != this->array.end() ; iter ++) {
		std::string value = iter->get()->getValue();
		if(!forEachFunc(value)) {
			return;
		}
	}
}

/**
 * @Author: CimZzz
 * @Date: 2022-06-30 18:22:06
 * 
 * 比较两个 Array 之间的区别
 * @param prop 属性指针
 * @return 如果相同返回 true
 */
bool ArrayProp::diff(VLProp* prop) {
	if(prop == nullptr) {
		return false;
	}
	if(prop->getType() != VLProp::PropType::Array) {
		return false;
	}
	ArrayProp* arrayProp = (ArrayProp*) prop;
	if(this->size() != arrayProp->size()) {
		return false;
	}

	std::set<std::string> set;
	for(auto i = this->array.begin() ; i != this->array.end() ; i ++) {
		set.insert(i->get()->getValue());
	}
	for(auto i = arrayProp->array.begin() ; i != arrayProp->array.end() ; i ++) {
		if(set.find(i->get()->getValue()) == set.end()) {
			return false;
		}
	}

	return true;
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-25 20:08:16
 * 
 * 克隆当前属性
 * 
 * @return 属性指针
 */
VLProp* ArrayProp::clone() {
	return new ArrayProp(*this);
}

/**
 * @Author: CimZzz
 * @Date: 2022-06-30 19:14:40
 * 
 * 组合属性
 * @param prop 属性指针
 * 
 * @return 组合成功返回 true
 */
bool ArrayProp::combine(std::shared_ptr<VLProp>& prop) {
	// ArrayProp 可以和 NodeProp 和 ArrayProp 合并, 其余类型 Prop 会标记为合并失败
	// 空节点默认为合并成功
	if(prop == nullptr || prop->isEmpty()) {
		return true;
	}

	if(!prop->isNode() && !prop->isArray()) {
		return false;
	}

	if(prop->isNode()) {
		if(this->conflictSet.find(prop->getValue()) == this->conflictSet.end()) {
			conflictSet.emplace(prop->getValue());
			this->array.push_back(prop);
		}
	} else {
		// 数组类型
		auto arrayPropPtr = (ArrayProp *) prop.get();
		for(auto iter = arrayPropPtr->array.begin() ; iter != arrayPropPtr->array.end() ; iter ++) {
			auto itemPtr = (*iter);
			if(this->conflictSet.find(itemPtr->getValue()) == this->conflictSet.end()) {
				conflictSet.emplace(itemPtr->getValue());
				this->array.push_back(itemPtr);
			}
		}
	}

	return true;
}

/**
 * @Author: CimZzz
 * @Date: 2022-11-07 18:00:52
 * 
 * 判断数组中是否包含某值
 * 
 * @param value 值字符串
 * 
 * @return 如果包含返回 true
 */
bool ArrayProp::contain(const std::string& value) {
	return this->conflictSet.find(value) != this->conflictSet.end();
}

/**
 * @Author: CimZzz
 * @Date: 2022-06-21 14:58:30
 * 
 * 删除指定下标元素
 * @param index 下标
 */
void ArrayProp::remove(unsigned int index) {
	if(index >= this->array.size()) {
		return;
	}
	this->array.erase(this->array.begin() + index);
}


/**
 * @Author: CimZzz
 * @Date: 2022-06-21 14:58:30
 * 
 * 清空全部元素
 */
void ArrayProp::clear() {
	this->array.clear();
}

/**
 * @Author: CimZzz
 * @Date: 2022-06-21 14:47:54
 * 
 * 获取数组长度
 * @return 数组长度
 */
unsigned int ArrayProp::size() {
	return this->array.size();
}


/**
 * @Author: CimZzz
 * @Date: 2022-06-21 11:04:46
 * 
 * 构建属性打印信息
 */
std::string ArrayProp::buildPropPrintInfo() {
	std::stringstream stream;
	stream << "(";
	if(this->getName() != "") {
		stream << "name: " << this->getName() << ", ";
	}
	stream << "size: " << this->array.size();
	stream << ")";
	return stream.str();
}

/**
 * @Author: CimZzz
 * @Date: 2022-06-21 15:16:41
 * 
 * 打印属性节点信息, 设置前缀
 * @param prefix 前缀
 */
void ArrayProp::printWithPrefix(std::string prefix) {
	VLProp::printWithPrefix(prefix);
	std::string childPrefix = "\t" + prefix;
	for(auto i = this->array.begin() ; i != this->array.end() ; i ++) {
		i->get()->printWithPrefix(childPrefix);
	}
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-19 18:51:05
 * 
 * 获取 Array 的起始迭代器
 * 
 * @return Array 的起始迭代器
 */
std::vector<std::shared_ptr<VLProp>>::iterator ArrayProp::begin() {
	return this->array.begin();
}

/**
 * @Author: CimZzz
 * @Date: 2022-08-19 18:51:05
 * 
 * 获取 Array 的终止迭代器
 * 
 * @return Array 的终止迭代器
 */
std::vector<std::shared_ptr<VLProp>>::iterator ArrayProp::end() {
	return this->array.end();
}